package com.demo.base.response;

import com.demo.constants.AppConstants;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.MDC;

/**
 * @author 曳戈泰尔
 * @version 1.0
 * @description 接口返回类
 * @date 2023/3/13 2:39 PM
 */
@Data
@Accessors(chain = true)
@ApiModel(value = "Result", description = "请求返回体")
public class Result<T> {

    @ApiModelProperty(value = "状态描述")
    private Status status;

    @ApiModelProperty(value = "状态码")
    private int code;

    @ApiModelProperty(value = "消息")
    private String message;

    @ApiModelProperty(value = "请求ID")
    private String requestId;

    @ApiModelProperty(value = "数据")
    private T data;

    private static <T> Result<T> create(Status status, int code, String message, T data) {
        // new方式实现多例模式
        return new Result<T>()
                .setStatus(status)
                .setCode(code)
                .setMessage(message)
                .setRequestId(MDC.get(AppConstants.HEADER_RID_NAME))
                .setData(data);
    }

    public static <T> Result<T> success(T data) {
        return create(Status.SUCCESS, Status.SUCCESS.ordinal(), "成功", data);
    }

    public static <T> Result<T> success() {
        return create(Status.SUCCESS, Status.SUCCESS.ordinal(), "成功", null);
    }

    public static <T> Result<T> fail(Status status, int code, String message) {
        return create(status, code, message, null);
    }

    public static <T> Result<T> fail(Status status) {
        return fail(status, status.ordinal(), StringUtils.EMPTY);
    }

    public static <T> Result<T> fail(String message) {
        return fail(Status.EXCEPTION, Status.EXCEPTION.ordinal(), message);
    }

    public static <T> Result<T> fail(Status status, String message) {
        return fail(status, status.ordinal(), message);
    }

    public static <T> Result<T> fail(int code, String message) {
        return fail(Status.EXCEPTION, code, message);
    }

    public static <T> Result<T> fail() {
        return fail(Status.EXCEPTION, Status.EXCEPTION.ordinal(), StringUtils.EMPTY);
    }

    public enum Status {
        SUCCESS,
        BAD_REQUEST,
        UNAUTHORIZED,
        VALIDATION_EXCEPTION,
        EXCEPTION,
        WRONG_CREDENTIALS,
        ACCESS_DENIED
    }
}
